package me.lwn.auth.application;

import me.lwn.auth.common.exception.MobileNotFoundException;
import me.lwn.auth.domain.User;
import me.lwn.auth.infrastructure.repository.UserRepository;
import me.lwn.auth.security.oauth2.server.authorization.ServerSetting;
import me.lwn.auth.security.oauth2.server.authorization.ServerSettingRepository;
import me.lwn.auth.security.utils.LocalMessageSource;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;

import static me.lwn.auth.security.utils.Constants.SPRING_SECURITY_FORGET_PASSWORD_SMS_CODE_CACHE_KEY;
import static me.lwn.auth.security.utils.Constants.SPRING_SECURITY_FORM_LOGIN_SMS_CODE_CACHE_KEY;

@Service
public class SmsManager {

    private final RedisTemplate<String, Object> redisTemplate;
    private final UserRepository userRepository;
    private final ServerSettingRepository settingRepository;
    private final MessageSourceAccessor message = LocalMessageSource.getAccessor();

    public SmsManager(RedisTemplate<String, Object> redisTemplate, UserRepository userRepository,
                      ServerSettingRepository settingRepository) {
        this.redisTemplate = redisTemplate;
        this.userRepository = userRepository;
        this.settingRepository = settingRepository;
    }

    private String sendSms(String mobile) {
        //TODO 短信发送
        return RandomStringUtils.randomNumeric(6);
    }

    private void checkMobile(String mobile) {
        User user = userRepository.getByMobile(mobile);
        if (user == null) {
            throw new MobileNotFoundException(this.message.getMessage("SmsManager.mobileNotFound", new String[]{mobile}));
        }
    }

    private long getCodeCacheDuration() {
        ServerSetting serverSetting = settingRepository.get();
        long duration = 300L;
        if (serverSetting != null) {
            duration = serverSetting.getSmsCodeTimeToLive();
        }
        return duration;
    }

    public String loginCode(String mobile) {
        checkMobile(mobile);
        String code = sendSms(mobile);
        redisTemplate.opsForValue().set(SPRING_SECURITY_FORM_LOGIN_SMS_CODE_CACHE_KEY + mobile, code,
                Duration.ofSeconds(getCodeCacheDuration()));
        return code;
    }

    public String forgetCode(String mobile) {
        checkMobile(mobile);
        String code = sendSms(mobile);
        redisTemplate.opsForValue().set(SPRING_SECURITY_FORGET_PASSWORD_SMS_CODE_CACHE_KEY + mobile, code,
                Duration.ofSeconds(getCodeCacheDuration()));
        return code;
    }
}
